package hc.server.ui.video;

import hc.App;
import hc.core.RootServerConnector;
import hc.core.util.IMsgNotifier;
import hc.util.ResourceUtil;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileOutputStream;
import java.net.URL;
import java.util.Properties;
import java.util.Vector;

import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.ProgressMonitor;
import javax.swing.ProgressMonitorInputStream;
import javax.swing.SwingConstants;

public class CapManager {

	public static void installJMF(){
		//检查安装环境只能为Windows
		final boolean isWindow = ResourceUtil.isWindowsOS();
		if(isWindow == false){
			String linuxDesc = "<html>" +
				"JMF online install only support Windows." +
				" please download and install JMF for other OS.<BR><BR>" +
				"The JMF 2.1.1 Reference Implementation supports SunVideo / SunVideoPlus capture devices on Solaris. " +
				"<BR>On Linux, devices that have a Video4Linux driver are expected to work, " +
				"but not extensively tested.<BR><BR>More info, please read 'Capture Devices' of Java Media Framework." +
				"<BR><BR>NOTE : If installed, please restart HomeCenter Server.</html>";
			JPanel notify = new JPanel();
			notify.add(new JLabel(linuxDesc, App.getSysIcon(App.SYS_WARN_ICON), SwingConstants.LEFT));
			App.showCenterPanel(notify, 0, 0, "install for other OS", false, null, null, null, null, false, false);
			return;
		}
		
		String windowDesc = "<html>" +
				"JMF install will auto detect and find USB camera(s). please wait for it.<BR><BR>" +
				"If you had installed JMF(Java Media Framework) 2.1.1, <BR>" +
				"please reinstall it, or check %CLASSPATH% system variable.</html>";
		JPanel notify = new JPanel();
		notify.add(new JLabel(windowDesc, App.getSysIcon(App.SYS_INFO_ICON), SwingConstants.LEFT));
		App.showCenterPanel(notify, 0, 0, "Install JMF (Java Media Framework)", true, null, 
				new ActionListener() {
					@Override
					public void actionPerformed(ActionEvent e) {
						downloadAndInstall();
					}
				}, 
				new ActionListener() {
					@Override
					public void actionPerformed(ActionEvent e) {
					}
				}, null, false, false);
	
	}

	private static void downloadAndInstall() {
		//ProgressMonitorInputStream需要另开线程来进行画面刷新
		new Thread(){
    		public void run(){
				final Properties thirdlibs = ResourceUtil.loadThirdLibs();
				if(thirdlibs == null){
					return;
				}
				
				final String md5Backup = "70129c04d56ce7301cf2c93857784268";
			
				ProgressMonitorInputStream pmis = null;
				FileOutputStream fos = null;
				File jfmExeFile;
				try{
					java.security.MessageDigest md = java.security.MessageDigest.getInstance( "MD5" );
					String tmpDir = System.getProperty("java.io.tmpdir");
					if(tmpDir == null ||tmpDir.length() == 0){
						tmpDir = "c:\\";
					}
					jfmExeFile = new File(tmpDir, "jmfInstall.exe");
					if(jfmExeFile.exists()){
						jfmExeFile.delete();
					}
					fos = new FileOutputStream(jfmExeFile);
					final byte[] bs = new byte[1024 * 5];
					URL url = new URL(thirdlibs.getProperty("jmf.url"));
					int total = url.openConnection().getContentLength();
					if(total <= 0){
						total = 20000000;
					}
					pmis = new ProgressMonitorInputStream(null, "download JMF install file...", url.openStream());
					
					ProgressMonitor progressMonitor = pmis.getProgressMonitor();
					progressMonitor.setMillisToDecideToPopup(1000);
					progressMonitor.setMillisToPopup(1000);
					progressMonitor.setMaximum(total);
					
					int readed = 0;
					int blockSize = 0;
					final long startMS = System.currentTimeMillis();
					long costMS = 0;
					while ((blockSize = pmis.read(bs)) != -1) {
						fos.write(bs, 0, blockSize);
						md.update(bs, 0, blockSize);
						
						readed += blockSize;
						
						float process = (float) readed / total * 100;// 算出百分比
						costMS = System.currentTimeMillis() - startMS;
						long leftSeconds = (costMS * total / readed - costMS) / 1000;
						
						progressMonitor.setNote("" + ((int)process) + "%, " + leftSeconds + " seconds");// 显示在进度条上
			      	}
					try{
						pmis.close();
					}catch (Exception e) {
					}
					try{
						fos.close();
					}catch (Exception e) {
					}
					String dnmd5 = ResourceUtil.toMD5(md.digest());
					if(dnmd5.equals(thirdlibs.getProperty("jmf.md5")) && dnmd5.equals(md5Backup)){
						final File jfmExeFileRef = jfmExeFile;
						new Thread(){
							public void run(){
								try{
									final String exeFileStr = jfmExeFileRef.getPath();
									Process process = Runtime.getRuntime().exec(exeFileStr);
									process.waitFor();  
								} catch (Exception e) {  
								   e.printStackTrace();  
								}
								JPanel panel = new JPanel();
								panel.add(new JLabel("Please restart HomeCenter Server later.", 
										App.getSysIcon(App.SYS_WARN_ICON), SwingConstants.LEFT));
								App.showCenterPanel(panel, 0, 0, "Restart", false, null, null, null, null, false, false);
							}
						}.start();
					}else{
						JOptionPane.showMessageDialog(null, "The install is invalid of MD5, please try after few minutes or install from oracle.com!", 
								"MD5 error", JOptionPane.ERROR_MESSAGE);
						return;
					}
				}catch (Exception e) {
					RootServerConnector.notifyLineOffType("lof=JmfErr");
					JOptionPane.showMessageDialog(null, "Error : " + e.toString(), "Error", JOptionPane.ERROR_MESSAGE);
				}finally{
					try{
						pmis.close();
					}catch (Exception e) {
						
					}
					try{
						fos.close();
					}catch (Exception e) {
						
					}
				}
    		}
		}.start();
	}

	//	private Raster rgbRaster;
	private static Vector<IMsgNotifier> listener = new Vector<IMsgNotifier>(1);

	public static void addListener(IMsgNotifier notify){
		synchronized(listener){
			if(listener.contains(notify) == false){
				listener.add(notify);
			}
		}
	}

	public static void removeListener(IMsgNotifier notify){
		listener.removeElement(notify);
	}

	public static void notifyMsg(int capStatus){
		synchronized(listener){
			final int size = CapManager.listener.size();
			final String strStatus = String.valueOf(capStatus);
			for (int i = 0; i < size; i++) {
				IMsgNotifier noti = CapManager.listener.elementAt(i);
				try{
					noti.notifyNewMsg(strStatus);
				}catch (Throwable e) {
				}
			}
		}
	}

}
